package cn.javabb.core.service.biz;

import cn.javabb.common.utils.ImageUtils;
import cn.javabb.common.utils.ListUtils;
import cn.javabb.core.annotation.RedisCache;
import cn.javabb.core.base.BaseService;
import cn.javabb.core.bo.PostBO;
import cn.javabb.core.constant.BizConstant;
import cn.javabb.core.constant.SysConstant;
import cn.javabb.core.entity.biz.*;
import cn.javabb.core.entity.sys.UserDO;
import cn.javabb.core.mapper.biz.PostMapper;
import cn.javabb.core.model.StatusEnum;
import cn.javabb.core.query.PostQuery;
import cn.javabb.core.service.sys.RedisService;
import cn.javabb.core.service.sys.SysConfigService;
import cn.javabb.core.service.sys.UserService;
import cn.javabb.core.util.ShiroUtil;
import cn.javabb.core.vo.PostVO;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.jarvis.cache.annotation.Cache;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author QINB imqinbao@163.com
 * @CreateDate 2018/11/23/023 16:29
 * @Since V1.0
 */
@Slf4j
@Service
public class PostService extends BaseService<PostDO> {

	@Autowired
	PostMapper postMapper;
	@Autowired
    UserService userService;
	@Autowired
	CommentService commentService;

	@Autowired
    SysConfigService sysConfigService;
	@Autowired
	CatalogService catalogService;
	@Autowired
	ContentService contentService;
	@Autowired
	PostHideService postHideService;
	@Autowired
	UserHideContentService userHideContentService;
	@Autowired
    RedisService redisService;
	// 帖子基本信息
	@RedisCache
	public List<PostDO> listPosts(JSONObject param) {
		param.put(this.SQLID, PostMapper.class.getName() + ".listPosts");
		return this.queryList(param);
	}

	/**
	 * 帖子列表 分页
	 * @param query
	 * @return
	 */
	public Page listPostsPage(PostQuery query) {
		Page p = PageHelper.startPage(query.getPage(), query.getSize());
		List<PostDO> list = postMapper.listPosts(query);
		return p;
	}
	// 帖子基本信息 分页
	public Page listPostsPage(JSONObject param) {
		param.put(this.SQLID, PostMapper.class.getName() + ".listPosts");
		return this.queryListPage(param);
	}

	/**
	 * 点击帖子-》获取帖子详细信息
	 * @param postId
	 * @param loginUserId
	 * @return
	 */
	public PostBO getPostDetail(Integer postId, Integer loginUserId){
		PostBO postBo = postMapper.get(postId);
		if(null == postBo){
			return null;
		}
		postBo.setCommentList(commentService.listCommentsByPostId(postId));
		CatalogDO catalog = catalogService.getCatalogById(postBo.getCatalogId());
		catalog.setTodayCount(postMapper.countTodayPostAndComment(postBo.getCatalogId()));
		postBo.setCatalog(catalog);
		//不管有没有隐藏内容，先默认设置不可见
		boolean showHideContent = false;
		UserDO loginUser = new UserDO();
		//1，判断用户是否登录，如果没有登录，所有隐藏内容是不可见
		if(null!=loginUserId){
			loginUser = userService.queryById(loginUserId);
			if(null != postBo.getHideContent() && StringUtils.isNotBlank(postBo.getHideContent().getContent())){
				//有隐藏内容		0为普通 1位隐藏内容 2登陆可见 3回复可见
				if(postBo.getUserId()==loginUserId){
					//如果是作者，当然可以看到全部了
					showHideContent = true;
				}else{
					// 判断类型，如果是购买可见
					if(postBo.getPostType()== BizConstant.POST_TYPE_HIDE){
						//用户是VIp 可见，不需要购买
						if(loginUser.getUserGrade()== SysConstant.USER_GRADE_VIP || loginUser.getUserGrade()==SysConstant.USER_GRADE_SUPERVIP){
							showHideContent = true;
						}else{
							showHideContent = userHideContentService.showHideContent(loginUserId, postBo.getHideContent().getId());
						}

					}else if(postBo.getPostType()==BizConstant.POST_TYPE_LOGIN){
						showHideContent = true;
					}else if(postBo.getPostType()==BizConstant.POST_TYPE_COMMENT){
						showHideContent = commentService.hasPostComment(loginUserId,postId);
					}
				}
				if(!showHideContent){
					// 如果发现，用户没有权限查看到隐藏内容，需要重新设置隐藏内容为空
					PostHideDO ah = postBo.getHideContent();
					ah.setContent("");
					postBo.setHideContent(ah);
				}

			}
		}
		postBo.setShowHideContent(showHideContent);
		return postBo;
	}

	/**
	 * 通过板块分类ID来查询帖子列表
	 * @param query
	 * @return
	 */
	public Page queryPageByCatalogId(PostQuery query) {
		Page p = PageHelper.startPage(query.getPage(), query.getSize());
		List<PostBO> articleboList =  postMapper.queryPage(query);
		return p;
	}

	/**
	 * 获取最新发布帖子,时间最新
	 *
	 * @param size
	 * @return
	 */
	public List<PostDO> listNewPosts(Integer size) {
		PostQuery query = new PostQuery();
		query.setSize(size);
		return this.listPostsPage(query).getResult();
	}

	/**
	 * 获取最新热门帖子，点击最多
	 *
	 * @param size
	 * @return
	 */
	@RedisCache
	public List<PostDO> listHotPosts(Integer size) {
		Example ex = new Example(PostDO.class);
		ex.createCriteria().andEqualTo("state", StatusEnum.NORMAL.getCode());
		ex.orderBy("clickCount").desc();
		return listPostsByEx(ex, size);
	}

	/**
	 * 获取最新推荐帖子
	 *
	 * @param size
	 * @return
	 */
	@RedisCache
	public List<PostDO> listSupportPosts(Integer size) {
		PostQuery query = new PostQuery();
		query.setSize(size);
		query.setPostSupport(1);
		Page page = listPostsPage(query);
		return page.getResult();
	}

	/**
	 * 获取置顶的帖子
	 *
	 * @param topType 置顶类型 1为栏目置顶，2为全站置顶
	 * @param size    数据大小
	 * @return
	 */
	public List<PostDO> listTopPosts(Integer topType, Integer size) {
		PostQuery query = new PostQuery();
		query.setSize(size);
		query.setPostTop(topType==null?BizConstant.POST_TOP_CATALOG:topType);
		Page page = listPostsPage(query);
		return page.getResult();
	}

	/**
	 * 最新评论过帖子
	 *
	 * @param size
	 * @return
	 */
	@RedisCache
	public List<PostDO> listCommentPosts(Integer size) {
		return postMapper.listCommentPosts(size);
	}
	@RedisCache
	public List<PostDO> listPostsByEx(Example ex, Integer size) {
		if (size != null) {
			PageHelper.startPage(1, size);
		}
		return this.queryListByExample(ex);
	}

	/**
	 * 获取帖子总数
	 *
	 * @param catalogId
	 * @return
	 */
	public Integer countPost(Integer catalogId) {
		PostDO post = new PostDO();
		post.setCatalogId(catalogId);
		post.setState(StatusEnum.NORMAL.getCode());
		return this.queryCountByWhere(post);
	}

	/**
	 * 帖子分类集合
	 * @return
	 */
	@RedisCache
	public Map<String,List<PostDO>> mapListPosts(Integer size){
		//置顶
		List<PostDO> topPosts = this.listTopPosts(BizConstant.POST_TOP_CATALOG,size);
		//推荐
		List<PostDO>  supportPosts = this.listSupportPosts(size);
		//最新
		List<PostDO> newPosts = this.listNewPosts(size);
		//最新评论
		List<PostDO> commentPosts = this.listCommentPosts(size);
		//强相关推荐
		//最热，点击最多
		List<PostDO> hotPosts = this.listHotPosts(size);
        // 最新有图片的帖子
        List<PostDO> imagePosts = this.listBannerPosts(size);

		Map<String,List<PostDO>> mapListPost = new HashMap<>();
		mapListPost.put("topPosts",topPosts);
		mapListPost.put("supportPosts",supportPosts);
		mapListPost.put("newPosts",newPosts);
		mapListPost.put("commentPosts",commentPosts);
		mapListPost.put("hotPosts",hotPosts);
		mapListPost.put("topPosts",topPosts);
        mapListPost.put("imagePosts",imagePosts);
		return mapListPost;
	}

	/**
	 * 论坛统计,包括今日，帖子，互动，最新用户
	 * @return
	 */
	@Cache(key = "mapCount",expire = 600)
	public Map<String,Object> mapCount(){
		JSONObject map = new JSONObject();
		map.put("countTodayPostAndComment", postMapper.countTodayPostAndComment(null));
		map.put("countPostAndComment",countPostAndComment(null));
		map.put("countUser",userService.CountUser());
		map.put("lastUser",userService.lastestUser());
		return map;
	}
	/**
	 * 获取所有主题数（帖子总数+评论总数）
	 *
	 * @return
	 */
	public Integer countPostAndComment(Integer catalogId) {
		CommentDO comment = new CommentDO();
		return countPost(null) + commentService.queryCountByWhere(null);
	}

	/**
	 * 保存帖子
	 *
	 * @param postVO
	 * @return
	 */
	@RedisCache(flush = true)
	@Transactional(rollbackFor = Exception.class)
	public boolean savePost(PostVO postVO) {
		// 保存帖子内容
		ContentDO content = new ContentDO();
		content.setContentHtml(postVO.getContent()).setContentId(postVO.getContentId());
		contentService.insertOrUpdateSelective(content);
		// 保存帖子信息
		PostDO postDO = new PostDO();
		postDO.setPostId(postVO.getPostId());
		postDO.setPostTitle(postVO.getPostTitle());
		postDO.setCatalogId(postVO.getCatalogId());
		postDO.setPostType(postVO.getPostType());
		postDO.setUserId(postVO.getUserId());
		postDO.setCommentState(postVO.getCommentState()==1?1:0);
		postDO.setClickCount(0).setState(StatusEnum.NORMAL.getCode());
		postDO.setContentId(content.getContentId());
		if(!CollectionUtils.isEmpty(ImageUtils.getImageByHtml(content.getContentHtml()))){
		    postDO.setCoverImage(ImageUtils.getImageByHtml(content.getContentHtml()).get(0));
        }
		this.insertOrUpdateSelective(postDO);
		// 如果帖子带有隐藏内容，则将隐藏内容插入到表中
		if (postVO.getPostType() == BizConstant.POST_TYPE_HIDE
				|| postVO.getPostType()  == BizConstant.POST_TYPE_LOGIN
				|| postVO.getPostType()  == BizConstant.POST_TYPE_COMMENT) {

			// insert articleHide
			PostHideDO ah = new PostHideDO();
			ah.setId(postVO.getHideContentId());
			ah.setPostId(postDO.getPostId());
			ah.setContent(postVO.getHideContent());
			ah.setPrice(postVO.getPrice());
			postHideService.insertOrUpdateSelective(ah);
		}
		if (null != postDO.getPostId()) {
			return true;
		}
		return false;
	}

	/**
	 * 插入帖子
	 *
	 * @param postDO
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class)
	public int insertPost(PostDO postDO) {
		postDO.setPostSupport(0);
		postDO.setPostTop(0);
		postDO.setClickCount(1);
		postDO.setState(StatusEnum.NORMAL.getCode());
		return this.insert(postDO);
	}
	/**
	 * 帖子点击
	 */
	@Transactional(rollbackFor = Exception.class)
	public int postClick(Integer postId){
		PostDO article = (PostDO)this.queryById(postId);
		int articleClick = 1;
		if(StringUtils.isNotBlank(sysConfigService.getConfigValue(BizConstant.CONFIG_ARTICLE_CLICK_CALC))){
			//postClick*2+5
			articleClick += Integer.parseInt(sysConfigService.getConfigValue(BizConstant.CONFIG_ARTICLE_CLICK_CALC));
		}
		article.setClickCount(article.getClickCount()+articleClick);
		int num = this.updateSelective(article);
		if(num>0){
			log.info("清除缓存*listArticlesByCatalogId*,*listTopArticles*");
			redisService.delBatch("*listPost*");
			redisService.delBatch("*listTop*");
		}
		return num;
	}

	/**
	 * 首页banner展示
	 * @param size
	 * @return
	 */
	public List<PostDO> listBannerPosts(int size){
        PageHelper.startPage(1, size);
        Example ex = new Example(PostDO.class);
        ex.createCriteria().andIsNotNull("coverImage")
                .andEqualTo("state", StatusEnum.NORMAL.getCode());
        ex.orderBy("createTime").desc();

		List<PostDO> postDOList = this.queryListByExample(ex);
		if(CollectionUtils.isEmpty(postDOList)){
			return null;
		}
		return postDOList;
	}
	// 修改置顶，只能是当前板块的置顶
	@Transactional(rollbackFor = Exception.class)
	public boolean updateTop(Integer postId,Integer top){
		PostDO article = new PostDO().setPostId(postId).setPostTop(top==1?1:0);
		if (this.updateSelective(article)>0) {
			return true;
		}
		return false;
	}
	// 修改精华
	@Transactional(rollbackFor = Exception.class)
	public boolean updateSupport(Integer postId,Integer support){
		PostDO article = new PostDO().setPostId(postId).setPostSupport(support==1?1:0);
		if (this.updateSelective(article)>0) {
			return true;
		}
		return false;
	}
	// 修改状态
	@Transactional(rollbackFor = Exception.class)
	public boolean updateState(Integer postId,Integer state){
		PostDO article = new PostDO().setPostId(postId).setState(state==1?1:0);
		if (this.updateSelective(article)>0) {
			return true;
		}
		return false;
	}

	/*删除帖子并删除内容,评论*/
	@Transactional(rollbackFor = Exception.class)
	public boolean delete(String ids) {
		List<String> idList = ListUtils.stringToListString(ids);
		int num = 0;
		for (String id : idList) {
			PostDO post = this.queryById(id);
			//删除帖子
			 num += this.deleteById(id);
			// 删除帖子内容
			contentService.deleteByWhere(new ContentDO().setContentId(post.getContentId()));
			// 删除这个帖子下面的评论
			commentService.deleteByWhere(new CommentDO().setArticleId(Integer.valueOf(id)).setArticleType(BizConstant.ARTICLE_TYPE_POST));
			// 刪除隐藏内容
			postHideService.deleteByWhere(new PostHideDO().setPostId(Integer.valueOf(id)));
		}
		return num>0;
	}
	/*根据用户删除帖子*/
	public boolean deleteByUserId(Integer userId) {
		PostDO post = new PostDO().setUserId(userId);
		List<PostDO> list = this.queryListByWhere(post);
		String ids = list.stream().map(x->String.valueOf(x.getPostId())).collect(Collectors.joining(","));
		return this.delete(ids);
	}
	/**
	 * 举报
	 * @param postId
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class)
	public boolean doReport(Integer postId) {
		return true;
	}
	/*判断该帖子是否可以评论*/
	public boolean checkCommentAble(Integer postId) {
		// 全局评论关闭，就不允许评论
		if (!sysConfigService.getGobalCommentState()) {
			return false;
		}
		PostDO post = new PostDO().setPostId(postId).setState(StatusEnum.NORMAL.getCode()).setCommentState(1);
		return this.queryCountByWhere(post)>0;
	}

	public boolean judgeSameUser(Integer postId) {
		PostDO post = this.queryById(postId);
		if (ShiroUtil.getLoginUser().getId().equals(post.getUserId())) {
			return true;
		}
		return false;

	}



}
